		TITLE	FIXUPP - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	GROUPS
		INCLUDE	FIXTEMPS
		INCLUDE	CDDATA

		PUBLIC	FIXUPP,FIXUPP32,BITS_TABLE,LOC_SIZE,FIXUPP_MODEND,LOC_11_DONE


		.DATA

		EXTERNDEF	NEW_FIXUPP:BYTE,TEMP_DATA_RECORD:BYTE,CLASS_TYPE:BYTE,LDATA_TYPE:BYTE,FARCALL_FIXUPP:BYTE
		EXTERNDEF	REFERENCE_FLAGS:BYTE

		EXTERNDEF	GRP_COUNT:DWORD,EXTERNAL_COUNT:DWORD,END_OF_RECORD:DWORD,LDATA_LENGTH:DWORD,NUMBLKS:DWORD
		EXTERNDEF	BUFFER_OFFSET:DWORD,EXTDEF_DELTA:DWORD,DEFAULT_SIZE:DWORD,LDATA_SEGMOD_GINDEX:DWORD
		EXTERNDEF	CURNMOD_GINDEX:DWORD,LATEST_PENT_GINDEX:DWORD,MODEND_OWNER_GINDEX:DWORD,GRP_LIST:DWORD
		EXTERNDEF	LAST_DATA_PTR:DWORD,LDATA_LOC:DWORD,PREV_DATA_PTR:DWORD,LAST_FARCALL:DWORD,FIRST_FARCALL:DWORD
		EXTERNDEF	MODEND_ADDRESS:DWORD,LOC_11_FIX:DWORD

		EXTERNDEF	GROUP_LARRAY:LARRAY_STRUCT,SEGMOD_LARRAY:LARRAY_STRUCT,SYMBOL_LARRAY:LARRAY_STRUCT
		EXTERNDEF	SYMBOL_GARRAY:STD_PTR_S,SEGMOD_GARRAY:STD_PTR_S,SEGMENT_GARRAY:STD_PTR_S,GROUP_GARRAY:STD_PTR_S

		EXTERNDEF	PRE_THREADS:THREAD_STUFF_STRUCT


		.CODE	PASS1_TEXT

		externdef	_farcall_alloc:proc
		externdef	_fixupp_alloc:proc
		externdef	_ldata_alloc:proc
		EXTERNDEF	FIXUPP_ALLOC:PROC,LDATA_ALLOC:PROC,LEDATA_CONT:PROC,INSTALL_PENT:PROC,FIXUPP_ERROR:PROC
		EXTERNDEF	OBJ_PHASE:PROC,FARCALL_ALLOC:PROC,_err_abort:proc,RETURN_LOWEST_SECTION:PROC,INSTALL_PUBALLOC:PROC
		EXTERNDEF	INSTALL_LIBALLOC:PROC,INSTALL_SOFT_REF:PROC,INSTALL_SOFT_PENT:PROC

		EXTERNDEF	FIXUPP_OFFSET_ERR:ABS,UNREC_FIXUPP_ERR:ABS,BAD_THREAD_ERR:ABS,BAD_LOC_ERR:ABS,LIDATA_ERR:ABS
		EXTERNDEF	UNRECOGNIZED_FIXUPP_FRAME_ERR:ABS


FIX_VARS	STRUC

FIX_SEGMOD_STUFF_BP	SEGMOD_STRUCT<>
FIX_FARCALL_PTR_BP	DD	?	;FIXUPP
FIX_NEW_PTR_BP		DD	?	;FIXUPP
FIX_OFFSET_BP		DD	?	;FIXUPP
FIX_LDATA_PTR_BP	DD	?	;FIXUPP - PHYSICAL ADDRESS
FIX_LDATA_BLK_BP	DD	?	;
FIX_FRAME_STUFF_BP	THREAD_STUFF_STRUCT<>
FIX_TARGET_STUFF_BP	THREAD_STUFF_STRUCT<>
FIX_LOC_BP		DD	?	;FIXUPP - NEXT NEED ODD BYTE
FIX_TOFFSET_BP		DD	?	;FIXUPP
FIX_LDATA_GROUP_GINDEX_BP	DD	?	;FIXUPP
FIX_LDATA_SEGMENT_GINDEX_BP	DD	?	;FIXUPP
FIXUPP_COUNT_BP		DD	?	;
FIX_END_OF_RECORD_BP	DD	?

FIX_NSYM_TYPE_BP	DB	?
FIX_SIZE_BP		DB	?	;FIXUPP&MODEND
FIX_SKIP_PENTS_BP	DB	?
FIX_COMDAT_PENTS_BP	DB	?

FIX_OS2_FLAGS_BP	DD	?	;
FIX_ESP_SAVE_BP		DD	?


FIX_VARS	ENDS

FIX	MACRO	X

X	EQU	([EBP - SIZE FIX_VARS].(X&_BP))

	ENDM

FIX	FIX_SEGMOD_STUFF
FIX	FIX_FARCALL_PTR
FIX	FIX_NEW_PTR
FIX	FIX_OFFSET
FIX	FIX_LDATA_PTR
FIX	FIX_LDATA_BLK
FIX	FIX_FRAME_STUFF
FIX	FIX_TARGET_STUFF
FIX	FIX_LOC
FIX	FIX_SIZE
FIX	FIX_TOFFSET
FIX	FIX_LDATA_GROUP_GINDEX
FIX	FIX_LDATA_SEGMENT_GINDEX
FIX	FIXUPP_COUNT
FIX	FIX_END_OF_RECORD
FIX	FIX_NSYM_TYPE
FIX	FIX_OS2_FLAGS
FIX	FIX_SKIP_PENTS
FIX	FIX_COMDAT_PENTS
FIX	FIX_ESP_SAVE


		ASSUME	EBP:PTR FIX_VARS

SCAN_FOR_THREADS	PROC
		;
		;skipping, so ok except that we must look for any thread
		;types so that threads are maintained...
		;
		MOV	AL,FIX_SIZE
		MOV	EBX,END_OF_RECORD

		MOV	EDX,2
		AND	AL,MASK BIT_32

		MOV	EDI,OFF NEW_FIXUPP
		JZ	SFT_1

		ADD	EDX,EDX
SFT_1:

LDI_LOOP	LABEL	PROC

		CMP	EBX,ESI
		JBE	DONE

		MOV	AL,[ESI]
		INC	ESI

		TEST	AL,80H
		JZ	HELP		;THREAD, JUMP
		;
		;skip this entry
		;
		MOV	AL,[ESI+1]
		ADD	ESI,2

		MOV	CL,AL
		TEST	AL,0C0H

		MOV	CH,[ESI]
		JNZ	NO_FRAME_INDEX

		AND	AL,30H
		INC	ESI

		CMP	AL,30H
		JZ	FORCE_2

		AND	CH,80H
		JZ	NO_FRAME_INDEX
FORCE_2:
		INC	ESI

NO_FRAME_INDEX	LABEL	PROC

		TEST	CL,8
		JNZ	NO_TARGET_INDEX

		MOV	AL,CL
		MOV	CH,[ESI]

		AND	AL,3
		INC	ESI

		CMP	AL,3
		JZ	FORCE_21

		AND	CH,80H
		JZ	NO_TARGET_INDEX
FORCE_21:
		INC	ESI

NO_TARGET_INDEX	LABEL	PROC

		TEST	CL,4
		JNZ	LDI_LOOP

		ADD	ESI,EDX		;2 OR 4
		JMP	LDI_LOOP	;19 VS 38

HELP		LABEL	PROC
		;
		;HERE COMES A THREAD DEFINITION, MUST BE PRESERVED....
		;
		MOV	[EDI],AL
		AND	AL,5CH		;ANY INDEX?
		INC	EDI
		CMP	AL,50H
		JNC	LDI_LOOP
		AND	AL,0CH		;YES, ONE OR TWO BYTES?
		MOV	AH,[ESI]
		INC	ESI
		MOV	[EDI],AH
		INC	EDI
		CMP	AL,0CH
		JZ	INC_TI
		TEST	AL,80H
		JZ	LDI_LOOP
INC_TI:
		MOV	AH,[ESI]
		INC	ESI
		MOV	[EDI],AH
		INC	EDI
		JMP	LDI_LOOP

DONE		LABEL	PROC
		;
		;IF ANY THREADS, WRITE'M
		;
		CMP	EDI,OFF NEW_FIXUPP
		JNZ	FIX_FIX
NOTHING_HERE1::
		JMP	NOTHING_HERE

SCAN_FOR_THREADS	ENDP


FIX_FIX		LABEL	PROC
		;
		;SET STUFF UP TO USE ABOVE CODE...
		;
		MOV	ESI,OFF NEW_FIXUPP
		MOV	END_OF_RECORD,EDI

		SHR	EDX,1
		XOR	EAX,EAX

		DEC	EDX
		MOV	LAST_DATA_PTR,EAX

;		MOV	FIX_LDATA_BLK,AX
		JMP	FIXUPP_CONTINUE


FIXUPP32	LABEL	PROC

		MOV	AL,MASK BIT_FI+MASK BIT_32
		JMP	FIXUPP_COMMON

SCAN_FOR_THREADS1:
		JMP	SCAN_FOR_THREADS


FIXUPP		PROC

		MOV	AL,MASK BIT_FI
if	fg_phar
		OR	AL,BPTR DEFAULT_SIZE
endif
FIXUPP_COMMON	LABEL	PROC
		;
		;
		;
		PUSH	EBP
		MOV	EBP,ESP

		SUB	ESP,SIZE FIX_VARS

		MOV	FIX_SIZE,AL
		XOR	EAX,EAX

		MOV	FIXUPP_COUNT,EAX
		MOV	FIX_LOC,EAX

		MOV	FIX_FRAME_STUFF.FS_TYPE,EAX
		MOV	FIX_TARGET_STUFF.FS_TYPE,EAX

		MOV	FIX_LDATA_BLK,EAX
		;
		;first we need to determine if this is a "keeper" record...
		;
		GETT	AL,LAST_DATA_KEEP

		MOV	EDI,END_OF_RECORD
		MOV	EDX,LAST_DATA_PTR
		ASSUME	EDX:PTR LDATA_HEADER_TYPE

		TEST	AL,AL
		JZ	SCAN_FOR_THREADS1

		SUB	EDI,ESI
		JZ	NOTHING_HERE1		;EMPTY FIXUPP, SKIP IT
		;
		;NEED LAST_DATA
		;
		MOV	AL,[EDX]._LD_TYPE
		PUSH	ESI

		AND	AL,MASK BIT_CONT
		JNZ	SPECIAL_LOAD

		LEA	EAX,[EDX + SIZE LDATA_HEADER_TYPE]
		MOV	FIX_LDATA_BLK,EDX	;PHYSICAL BLOCK # - FOR UNLOCKING

		MOV	FIX_LDATA_PTR,EAX
		JMP	LOAD_DONE


SPECIAL_LOAD	LABEL	PROC
		;
		;THIS GUY IS SPLIT OVER TWO BLOCKS, MOVE HIM TO LOCAL STORAGE
		;
		MOV	ESI,EDX
		MOV	ECX,SIZE LDATA_HEADER_TYPE/4

		MOV	EDI,OFF TEMP_DATA_RECORD
		MOV	EBX,DPTR [EDX]._LD_LENGTH	;DATA LENGTH

		REP	MOVSD

		MOV	ECX,[EDX]._LD_BLOCK_BASE;NEXT LOGICAL BLOCK #
		MOV	FIX_LDATA_PTR,EDI

		MOV	EAX,ECX
		ADD	ECX,PAGE_SIZE

		SUB	ECX,ESI
		AND	EBX,0FFFFH

		SUB	EBX,ECX		;SAVE THIS #
		SHR	ECX,2

		REP	MOVSD

		LEA	ECX,[EBX+3]
		MOV	ESI,[EAX+4]

		SHR	ECX,2
		ADD	ESI,BLOCK_BASE

		REP	MOVSD

		MOV	FIX_LDATA_BLK,ECX	;NO BLOCK TO UNLOCK...

		ASSUME	EDX:NOTHING

LOAD_DONE	LABEL	PROC
		;
		;NOW SET UP STUFF TO BE USED BY EXECUTE
		;
		MOV	EAX,FIX_LDATA_PTR
		MOV	ESI,LDATA_SEGMOD_GINDEX
		CONVERT	ESI,ESI,SEGMOD_GARRAY

		ADD	EAX,LDATA_LENGTH
		MOV	ECX,(SIZE SEGMOD_STRUCT+3)/4

		MOV	FIX_END_OF_RECORD,EAX
		LEA	EDI,FIX_SEGMOD_STUFF

		REP	MOVSD

		MOV	EAX,FIX_SEGMOD_STUFF._SM_BASE_SEG_GINDEX
		MOV	FIX_OS2_FLAGS,ECX

		MOV	FIX_LDATA_SEGMENT_GINDEX,EAX
if	fg_segm
		MOV	FIX_SKIP_PENTS,CL

		MOV	FIX_COMDAT_PENTS,CL
endif
		TEST	EAX,EAX
		JZ	NO_BASE_SEG
		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

		MOV	DL,FIX_SEGMOD_STUFF._SM_FLAGS
		MOV	ECX,[EAX]._SEG_OS2_FLAGS

		MOV	EAX,[EAX]._SEG_GROUP_GINDEX
		ASSUME	EAX:NOTHING
		MOV	FIX_OS2_FLAGS,ECX

		AND	DL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	YSP
if	fg_segm
		BITT	PROTMODE			;CANNOT SKIP IF REALMODE
		JZ	NSP
		;
		;IF PROTMODE, ONLY DO THIS IF CURRENT SEGMENT IS NOT IOPL-NONCONFORMING-CODE
		;
		MOV	ECX,FIX_LDATA_SEGMENT_GINDEX
		MOV	EDX,FIX_OS2_FLAGS

		TEST	ECX,ECX				;WE DON'T KNOW SEGMENT, DO IT
		JZ	NSP

		TEST	EDX,MASK SR_CONF+1		;CONFORMING OR DATA, CANNOT SKIP
		JNZ	NSP

		AND	EDX,1 SHL SR_DPL		;NOT IOPL, CANNOT SKIP
		JZ	NSP
endif
YSP:
		MOV	FIX_SKIP_PENTS,-1
NSP:
NO_BASE_SEG:
		MOV	FIX_LDATA_GROUP_GINDEX,EAX
		;
		;CALCULATE FIX_COMDAT_PENTS
		;
		BITT	ENTRIES_POSSIBLE
		JZ	NCP
		BITT	LAST_DATA_COMDAT
		JZ	NCP
		;
		;THIS IS ONE OF TWO CASES:
		;
		;	1. UNREFERENCED COMDATS - WE WILL DECREMENT PENT COUNTS IF NEVER REFERENCED
		;	2. REFERENCED BUT NO KNOWN SEGMENT - WE WILL ADJUST IF PROTMODE AND IOPL
		;
		CMP	REFERENCE_FLAGS,MASK S_SOFT_REF
		JZ	YCP
		CMP	FIX_LDATA_SEGMENT_GINDEX,0
		JNZ	NCP
		BITT	PROTMODE
		JZ	NCP			;WE KEEP ALL IN REAL MODE
YCP:
		MOV	FIX_COMDAT_PENTS,-1
NCP:
		POP	ESI
		MOV	EDI,END_OF_RECORD

FIXUPP_CONTINUE	LABEL	PROC

		SUB	EDI,ESI
		JZ	NOTHING_HERE

		MOV	FIX_NEW_PTR,OFF NEW_FIXUPP
if	fg_norm_exe OR fg_segm
		MOV	FIX_FARCALL_PTR,OFF FARCALL_FIXUPP
endif
		CALL	PRE_FIXUPPS

		CALL	RELEASE_LDATA_RECORD

		CALL	FLUSH_NEWFIXUPP
if	fg_norm_exe OR fg_segm
		CALL	FLUSH_FARCALL
endif
NOTHING_HERE	LABEL	PROC

		CALL	UPDATE_FIXUPP_COUNT

		MOV	ESP,EBP
		POP	EBP
		RET

FIXUPP		ENDP


UPDATE_FIXUPP_COUNT	PROC	NEAR
		;
		;
		;
		MOV	ECX,FIXUPP_COUNT
		MOV	EAX,LDATA_SEGMOD_GINDEX

		TEST	ECX,ECX
		JZ	FGP_9

		TEST	EAX,EAX			;CODEVIEW IGNORED?
		JZ	FGP_9

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		ADD	[EAX]._SM_RELOC_CNT,ECX
FGP_9:
		RET

UPDATE_FIXUPP_COUNT	ENDP

		ASSUME	EAX:NOTHING


RELEASE_LDATA_RECORD	PROC	NEAR
		;
		;
		;
		MOV	EAX,FIX_LDATA_BLK
		MOV	EDI,LAST_DATA_PTR

		TEST	EAX,EAX
		JZ	L1$
L0$:
		RET

L1$:
		;
		;MUST COPY BACK TO VIRTUAL SPACE
		;
		TEST	EDI,EDI
		MOV	ESI,OFF TEMP_DATA_RECORD
		ASSUME	ESI:PTR LDATA_HEADER_TYPE

		MOV	ECX,SIZE LDATA_HEADER_TYPE/4
		JZ	L0$

		MOV	EBX,ESI
		ASSUME	EBX:PTR LDATA_HEADER_TYPE
		MOV	EAX,[ESI]._LD_BLOCK_BASE

		REP	MOVSD

		MOV	EBX,DPTR [EBX]._LD_LENGTH	;DATA LENGTH
		MOV	ECX,EAX

		AND	EBX,0FFFFH
		ADD	ECX,PAGE_SIZE	;BLOCK SIZE

		SUB	ECX,EDI

		SUB	EBX,ECX		;SAVE THIS #
		SHR	ECX,2

		REP	MOVSD

		LEA	ECX,[EBX+3]
		MOV	EDI,[EAX+4]

		SHR	ECX,2
		ADD	EDI,BLOCK_BASE

		REP	MOVSD

		RET

RELEASE_LDATA_RECORD	ENDP

		ASSUME	ESI:NOTHING,EBX:NOTHING


FLUSH_NEWFIXUPP	PROC	NEAR
		;
		;
		;
		MOV	ESI,OFF NEW_FIXUPP
		MOV	ECX,FIX_NEW_PTR

		SUB	ECX,ESI
		JZ	L9$

		MOV	FIX_NEW_PTR,ESI
		MOV	EDX,LAST_DATA_PTR

		MOV	EDI,ECX
		LEA	EAX,[ECX + SIZE FIXUPP_HEADER_TYPE]

		MOV	CL,FIX_SIZE
		PUSH	EDX

		PUSH	ECX
SPEC_RET:
		sub	ESP,12
		mov	EDX,ESP
		push	EDX		; &EAX
		add	EDX,4
		push	EDX		; &ECX
		add	EDX,4
		push	EDX		; &EDX
		push	EAX
		call	_fixupp_alloc
		add	ESP,16
		test	EAX,EAX
		pop	EAX
		pop	ECX
		pop	EDX
		jnz	SPECIAL
;		CALL	FIXUPP_ALLOC	;EAX = BLOCK_BASE, ECX PHYS
;		JC	SPECIAL
		MOV	EDX,EDI
SPEC_2:
		ASSUME	ECX:PTR FIXUPP_HEADER_TYPE

		MOV	[ECX]._FH_BLOCK_BASE,EAX

		XOR	EAX,EAX
		MOV	LAST_DATA_PTR,ECX	;SAVE OFFSET TOO
		;
		;NEXT_LDATA
		;TYPE
		;SECOND_BLK
		;LENGTH
		;
		MOV	[ECX]._FH_NEXT_FIXUPP,EAX
		MOV	AL,FIX_SIZE

		SHL	EAX,16
		OR	EAX,EDI
		MOV	DPTR [ECX]._FH_LENGTH,EAX

		MOV	EAX,EBX			;SECOND BLOCK
		MOV	EBX,EDI			;# OF BYTES
		LEA	EDI,[ECX+ SIZEOF FIXUPP_HEADER_TYPE]	;DESTINATION
		MOV	ECX,EDX			;# IN FIRST BLOCK
		MOV	EDX,EAX			;SECOND BLOCK

		CALL	LEDATA_CONT

		POPM	ECX,EAX

		MOV	FIX_SIZE,CL
		MOV	LAST_DATA_PTR,EAX
L9$:
		RET

SPECIAL:
		SUB	EDX,SIZE FIXUPP_HEADER_TYPE	;I WANT HEADER MINIMUM
		JC	SPEC1
		;
		;HARD ONE, SET UP STUFF FOR DOING IT CORRECTLY...
		;
		PUSHM	EAX,ECX,EDX
		OR	FIX_SIZE,MASK BIT_CONT

		MOV	EAX,EDI
		MOV	LAST_DATA_PTR,ECX

		SUB	EAX,EDX		;NEED THIS MANY MORE

		sub	ESP,12
		mov	EDX,ESP
		push	EDX		; &EAX
		add	EDX,4
		push	EDX		; &ECX
		add	EDX,4
		push	EDX		; &EDX
		push	EAX
		call	_ldata_alloc
		add	ESP,16
		pop	EAX
		pop	ECX
		pop	EDX
;		CALL	LDATA_ALLOC	;GET MORE...

		POP	EDX
		MOV	EBX,ECX

		POPM	ECX,EAX

		JMP	SPEC_2

SPEC1:
		;
		;CANT EVEN FIT HEADER, RELEASE THIS
		;
		DEC	DPTR [EAX]	;DON'T COUNT THAT GUY
		LEA	EAX,[EDI+SIZE FIXUPP_HEADER_TYPE]
		JMP	SPEC_RET

FLUSH_NEWFIXUPP	ENDP


FLUSH_FARCALL	PROC	NEAR
		;
		;
		;
		MOV	ESI,OFF FARCALL_FIXUPP
		MOV	ECX,FIX_FARCALL_PTR

		MOV	FIX_FARCALL_PTR,ESI
		SUB	ECX,ESI

		MOV	EDI,ECX
		JZ	L9$

		LEA	EAX,[ECX + SIZE FARCALL_HEADER_TYPE]
FAR_SPEC_RET:
		sub	ESP,8
		mov	EDX,ESP
		push	EDX		; pECX
		add	EDX,4
		push	EDX		; pEAX
		push	EAX
		call	_farcall_alloc
		add	ESP,12
		mov	EDX,EAX
		pop	ECX
		pop	EAX
		test	EDX,EDX
		jnz	FAR_SPECIAL
;		CALL	FARCALL_ALLOC	;EAX=BLK BASE, ECX IS PHYS
;		JC	FAR_SPECIAL

		XOR	EDX,EDX
		ASSUME	ECX:PTR FARCALL_HEADER_TYPE
		;
		;NEXT_FARCALL
		;SEGMENT
		;LENGTH
		;
		MOV	EBX,EDI

		MOV	[ECX]._FC_BLOCK_BASE,EAX
		MOV	[ECX]._FC_NEXT_FARCALL,EDX

		MOV	EAX,LDATA_SEGMOD_GINDEX
		MOV	[ECX]._FC_LENGTH,EDI

		MOV	[ECX]._FC_SEGMOD_GINDEX,EAX
		LEA	EDI,[ECX + SIZE FARCALL_HEADER_TYPE]

		MOV	EAX,ECX
		LEA	ECX,[EBX+3]
		;
		;NOW MOVE REST OF FIRST BLOCK
		;
		SHR	ECX,2
		MOV	EDX,LAST_FARCALL

		REP	MOVSD
		;
		;NOW, LINK THIS TO FARCALL_LIST
		;
		TEST	EDX,EDX
		JZ	FIRST_FARCALL_

		MOV	[EDX].FARCALL_HEADER_TYPE._FC_NEXT_FARCALL,EAX
FF_RET:
		MOV	LAST_FARCALL,EAX
L9$:
		RET

FAR_SPECIAL:
		DEC	DPTR [EAX]
		LEA	EAX,[EDI + SIZE FARCALL_HEADER_TYPE]
		JMP	FAR_SPEC_RET


FIRST_FARCALL_:
		MOV	FIRST_FARCALL,EAX
		JMP	FF_RET

FLUSH_FARCALL	ENDP

		ASSUME	ECX:NOTHING


DO_THREAD	PROC
		;
		;HERE FOR DEFINING A NEW THREAD...
		;
		;	BIT
		;  7  6  5  4  3  2  1  0
		;  0  D  0   METHOD  THRED
		;
		;WHERE  D=0 = TARGET
		;	D=1 = FRAME
		;
		;I WANT BX TO BE D:METHOD IN BITS 4-1
		;I WANT DI TO BE D:THRED IN BITS 5-3
		;I WANT AX TO BE METHOD IN BITS 3-1
		;
		;IF D = 0, METHOD=METHOD MOD 4
		;
		AND	EAX,7FH

		MOV	ECX,EAX
		MOV	EDX,EAX

		SHR	AL,2
		AND	ECX,40H		;CL IS JUST D BIT

		AND	EDX,3		;DL IS THREAD
		AND	AL,7		;AL IS METHOD

		SHR	CL,3
		ADD	EDX,EDX

		MOV	EBX,EAX		;EBX IS METHOD
		OR	AL,CL		;EAX IS D:METHOD

		OR	DL,CL
		TEST	CL,CL

		JNZ	DT_1

		AND	EBX,3
DT_1:
		LEA	EDI,PRE_THREADS[EDX*8]
		MOV	BUFFER_OFFSET,ESI

		MOV	CL,-1

		MOV	[EDI],EBX
		MOV	BPTR [EDI+8],CL

		ADD	EDI,4
		CALL	DT_TABLE[EAX*4]

DO_THREAD	ENDP


PRE_FIXUPPS	PROC
		;			ES MUST BE DGROUP HERE!
		CMP	END_OF_RECORD,ESI
		JBE	DONE_FIXUPPS

		MOV	AL,[ESI]
		INC	ESI

		TEST	AL,80H
		JZ	DO_THREAD	;THREAD DEFINITION
		;
		;HERE COMES THE REAL FIXUPPS
		;
		MOV	AH,AL
		SHR	AL,2
if	fg_phar
		MOV	CL,BPTR DEFAULT_SIZE	;IF PHARLAP, CONVERT TO MS RECORD TYPE
endif
		AND	EAX,031FH
if	fg_phar
		TEST	CL,CL
		JNZ	L1$
L19$:
endif
		MOV	BPTR FIX_LOC,AL		;FIXUPP TYPE1
		MOV	AL,[ESI]		;EAX IS RECORD OFFSET
		;
		;VERIFY RANGE FOR LDATA - MAKE SURE FIXUPP DOESN'T POINT PAST END OF RECORD
		;
		MOV	EBX,LDATA_LENGTH
		INC	ESI

		SUB	EBX,EAX
		JC	BOUNDS_FAIL

		CMP	EBX,6
		MOV	FIX_OFFSET,EAX

		MOV	EAX,FIX_LOC
		JC	FURTHER_TESTING		;MUST DETERMINE LOC TYPE...
FT_RET:
		CALL	PRELIM			;READ FRAME AND TARGET
		PUSH	ESI
		;
		;NOW, SEE IF WE CAN REDUCE THE FRAME/TARGETS
		;VALID FRAME-TYPES ARE
		;
		;	0	SEGMENT FOLLOWS
		;	1	GROUP FOLLOWS
		;	2	EXTERNAL FOLLOWS
		;	3	ABSOLUTE FOLLOWS
		;	4	LOC		*
		;	5	TARG		*
		;	6	??
		;	7	??
		;	8	GROUP(LOC)	*
		;	9	GROUP(TARG)	*
		;	A	DGROUP
		;	B	GROUP 1
		;	C	GROUP 2
		;
if	fg_pe
		GETT	AL,OUTPUT_PE	;PE OUTPUT IS FLAT, FRAME == TARG

		OR	AL,AL
		JNZ	MCV_TARG
endif
		MOV	AL,FIX_SEGMOD_STUFF._SM_FLAGS

		TEST	AL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	MCV_BASE
MCV_RET:
		MOV	EBX,FIX_FRAME_STUFF.FS_TYPE
		MOV	ECX,FIX_FRAME_STUFF.FS_INDEX

		MOV	EDX,FIX_TARGET_STUFF.FS_TYPE
		MOV	EDI,FIX_TARGET_STUFF.FS_INDEX

		JMP	FRAME_OPTI_TABLE[EBX*4]

MCV_BASE:
		GETT	AL,CV_4_TYPE

		OR	AL,AL
		JZ	MCV_RET
MCV_TARG:
		JMP	FRAME_TARG

if	fg_phar

L1$:
		MOV	EBX,OFF PHAR_TO_MS		;IF PHARLAP, CONVERT TO MS
		XLAT	[PHAR_TO_MS]
		JMP	L19$

endif

PE:
		CALL	OBJ_PHASE
		RET

DONE_FIXUPPS:
		JNZ	PE
		RET

FURTHER_TESTING:
		;
		CMP	BL,LOC_SIZE[EAX]
		JNC	FT_RET
BOUNDS_FAIL:
		;
		;ERROR...
		;
		MOV	AL,FIXUPP_OFFSET_ERR
		CALL	FIXUPP_ERROR
		CALL	PRELIM
		JMP	PRE_FIXUPPS


FRAME_ABSOLUTE	LABEL	PROC
		;
		;FRAME IS ABSOLUTE.  TO OPTIMIZE, TARGET MUST BE MATCHING
		;ABSOLUTE
		;
		CMP	EDX,FS_TYPE_ASEG
		JNZ	FRAME_OPTIMUM

		CMP	EDI,ECX
		JZ	FRAME_TARG
		JMP	FRAME_OPTIMUM

FRAME_EXTERNAL	LABEL	PROC
		;
		;FRAME IS AN EXTERNAL.  TO OPTIMIZE, TARGET MUST BE MATCHING
		;EXTERNAL
		;
		CMP	EDX,FS_TYPE_SYMBOL
		JNZ	FRAME_OPTIMUM

		CMP	EDI,ECX
		JNZ	FRAME_OPTIMUM
FRAME_TARG:
		MOV	BPTR FIX_FRAME_STUFF.FS_TYPE,FS_TYPE_TARG
FRAME_OPTIMUM::
		;
		MOV	ESI,FIX_LOC
		CALL	EXECUTE_FIXUPP	;THIS GUY HANDLES OFFSET-REDUCTION

		CALL	STORE_OPTIMAL
OPTIMIZED_OUT:
		POP	ESI
		JMP	PRE_FIXUPPS


FRAME_SEGMENT::
		;
		;FRAME IS A SEGMENT.  TO OPTIMIZE, TARGET MUST BE MATCHING
		;SEGMENT, OR EXTERNAL IN SAME SEGMENT, OR LASTLY = LOCATION
		;  OR ASEG
		;
;		MOV	BX,FIX_TARGET_STUFF.FS_TYPE
		
		JMP	FRAME_SEGMENT_TABLE[EDX*4]

F_SEG_T_EXT::
;		MOV	EDI,FIX_TARGET_STUFF.FS_INDEX
		CONVERT	EDI,EDI,SYMBOL_GARRAY
		ASSUME	EDI:PTR SYMBOL_STRUCT

		;
		;SYMBOL MUST BE DEFINED, NO GROUP, SEGMENTS MATCHING
		;
		MOV	AL,[EDI]._S_NSYM_TYPE

		CMP	AL,NSYM_CONST
		JZ	FRAME_TARG

		CMP	AL,NSYM_RELOC
		JA	TRY_LOC

		CMP	AL,NSYM_ASEG
		JB	TRY_LOC

		MOV	AL,[EDI]._S_REF_FLAGS
		MOV	EDI,[EDI]._S_SEG_GINDEX

		TEST	AL,MASK S_USE_GROUP
		JNZ	TRY_LOC
F_SEG_T_SEG::
		;
		;BOTH ARE SEGMENTS, DO THEY MATCH?
		;
FSTS_CONT:
		CONVERT	EDI,EDI,SEGMOD_GARRAY
		ASSUME	EDI:PTR SEGMOD_STRUCT

		CMP	[EDI]._SM_BASE_SEG_GINDEX,ECX	;MUST MATCH BASE
		JZ	FRAME_TARG			;SEGMENT
TRY_LOC::
		;
		;TRY FOR 'LOC'
		;
		CMP	FIX_LDATA_SEGMENT_GINDEX,ECX
		JNZ	FRAME_OPTIMUM
YES_LOC::
		MOV	BPTR FIX_FRAME_STUFF.FS_TYPE,FS_TYPE_LOC	;LOC*2

		JMP	FRAME_OPTIMUM

PRE_FIXUPPS	ENDP

		ASSUME	EDI:NOTHING


STORE_OPTIMAL_MODEND	LABEL	PROC

		MOV	EDI,FIX_NEW_PTR
		MOV	EAX,13H SHL (26)

		ADD	EDI,4
		JMP	OPT_0


STORE_OPTIMAL	PROC
		;
		;STORE OPTIMAL FIXUPP REPRESENTATION
		;
		MOV	EAX,FIX_TARGET_STUFF.FS_TYPE
		MOV	EDI,FIX_NEW_PTR

		CMP	AL,-1
		JZ	L9$

		MOV	EAX,FIX_LOC
		ADD	EDI,4

		SHL	EAX,10
		MOV	ECX,FIX_OFFSET

		LEA	ESI,FIX_TARGET_STUFF
		OR	EAX,ECX

		SHL	EAX,16			;LOC-TYPE AND OFFSET
OPT_0::
		CALL	STORE_OPTI

		MOV	FIX_NEW_PTR,EDI
		CMP	EDI,OFF NEW_FIXUPP+NEW_FIXUPP_SIZE-16

		JAE	FLUSH_NEWFIXUPP
L9$:
		RET

STORE_OPTIMAL	ENDP


STORE_OPTI	PROC	NEAR
		;
		;
		;
		ASSUME	ESI:PTR THREAD_STUFF_STRUCT

		MOV	AH,BPTR [ESI].FS_TYPE	;TARGET TYPE, 0=SEGMOD, 1=GROUP, 2=EXTERN, 3=ASEG
		MOV	ECX,[ESI].FS_INDEX

		MOV	EDX,FIX_TOFFSET		;OFFSET
		LEA	EBX,[EDI-4]		;PLACE TO STORE THIS

		MOV	[EDI],ECX
		ADD	EDI,4

		TEST	EDX,EDX
		JZ	L1$

		MOV	[EDI],EDX
		ADD	EDI,4

		OR	AH,10H
L1$:
		;
		;NOW DO FRAME
		;
		MOV	AL,BPTR FIX_FRAME_STUFF.FS_TYPE	;FRAME  0=SEG, 1=GRP, 2=EXT, 3=ASEG, 4=LOC, 5=TARG
		MOV	ECX,FIX_FRAME_STUFF.FS_INDEX

		CMP	AL,3
		JA	L6$

		CMP	AL,1
		JNZ	L5$

		MOV	EDX,[ECX].GROUP_STRUCT._G_NUMBER

		CMP	EDX,16
		JA	L5$

		LEA	EAX,[EAX+EDX+5]
		JMP	L6$

L5$:
		MOV	[EDI],ECX
		ADD	EDI,4
L6$:
		MOV	[EBX],EAX
		RET

STORE_OPTI	ENDP


EXECUTE_FIXUPP	PROC	NEAR
		;
		;NOW SEE IF ANYONE CAN REDUCE OFFSET OR MAYBE COMPLETE FIXUP..
		;
		;SAVE DS:SI
		;
if	alloc_support
		TEST	FIX_SEGMOD_STUFF._SM_FLAGS,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	200$
		;
		;HANDLE REFERENCES TO AN ALLOCATABLE SEGMOD
		;
		CMP	FIX_TARGET_STUFF.FS_TYPE,4	;EXTERNAL?
		JNZ	2$				;NO, TRY SEGMENT
		PUSHM	DS,SI
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		ASSUME	DS:NOTHING
		SYM_CONV_DS
		;
		;BASICALLY, IF ASEG OR CONST OR IMPORT, IGNORE.  ELSE
		;PROCESS ACCESS BY THIS SEGMOD.
		;
		TEST	[SI]._S_PLTYPE,MASK LEVEL_0_SECTION;ALREADY REFERENCED
		JNZ	19$			;FROM LEVEL 0, IGNORE
		;
		;IF WE KNOW THIS SYMBOL WILL BE VECTORED, AND WE ARE NOT
		;ALLOCATING, THIS STUFF COULD ALL BE SKIPPED
		;.......
		;
		;
		LEA	SI,_S_SECTION[SI]
		FIXES
		LEA	DI,FIX_SEGMOD_STUFF._SM_SECTION
		CALL	RETURN_LOWEST_SECTION	;DX:BX
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		SYM_CONV_DS
		CMP	[SI]._S_SECTION.OFFS,BX
		JZ	14$
		MOV	[SI]._S_SECTION.OFFS,BX
11$:
		MOV	[SI]._S_SECTION.SEGM,DX
		OR	DX,DX
		JZ	12$
		MOV	ES,DX			;SEE IF NOW LEVEL_0
		SYM_CONV_ES
		CMP	ES:[BX]._SECT_LEVEL,0
		JNZ	12$
		OR	[SI]._S_PLTYPE,MASK LEVEL_0_SECTION
		;
		;WHAT ABOUT UPDATING THE SEGMOD, AND WHAT ABOUT OTHER PUBLICS
		;IN THAT SEGMOD?  AND WHAT THEN ABOUT RELEASING ANY OF THAT
		;STORAGE?
		;
		;WE NEED TO UPDATE THE SEGMOD IFF IT IS ALLOCATABLE.
		;
		


		;
		;WELL, DON'T CARE ABOUT ANYTHING ELSE IF LEVEL 0 SECTION..
		;
		JMP	19$

14$:
		CMP	[SI]._S_SECTION.SEGM,DX
		JNZ	11$
12$:
		;
		;NOW, IF THIS SEGMOD IS ALLOCATABLE, ADD
		;
		TEST	FIX_SEGMOD_STUFF._SM_PLTYPE,MASK SECTION_ASSIGNED
		JNZ	19$				;NOT ALLOCATABLE
		;
		;ADD THIS SEGMOD TO LIST OF ALLOCATABLE SEGMODS REFERENCING
		;THIS SYMBOL
		;
		MOV	DX,FIX_TARGET_STUFF.FS_PTR.SEGM
		MOV	CX,FIX_TARGET_STUFF.FS_PTR.OFFS
		MOV	AX,LDATA_SEGMOD.SEGM
		MOV	BX,LDATA_SEGMOD.OFFS
		CALL	INSTALL_PUBALLOC
19$:
		POPM	SI,DS
191$:
		JMP	3$

2$:
		;
		;IF AN ALLOCATABLE SEGMOD, PROCESS ACCESS BY 'THIS' SEGMOD
		;
		CMP	FIX_TARGET_STUFF.FS_TYPE,0	;SEGMOD?
200$:
		JNZ	191$
		;
		;IGNORE IF SELF REFERENTIAL...
		;
		MOV	AX,FIX_TARGET_STUFF.FS_PTR.OFFS
		CMP	LDATA_SEGMOD.OFFS,AX
		JZ	28$
20$:
		PUSHM	DS,SI
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		ASSUME	DS:NOTHING
		SYM_CONV_DS
		TEST	[SI]._SM_PLTYPE,MASK SECTION_ASSIGNED+MASK LEVEL_0_SECTION
		JNZ	29$
		LEA	SI,_SM_SECTION[SI]
		FIXES
		LEA	DI,FIX_SEGMOD_STUFF._SM_SECTION
		CALL	RETURN_LOWEST_SECTION		;DX:BX
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		SYM_CONV_DS
		CMP	[SI]._SM_SECTION.OFFS,BX
		JZ	24$
		MOV	[SI]._SM_SECTION.OFFS,BX
21$:
		MOV	[SI]._SM_SECTION.SEGM,DX
		OR	DX,DX
		JZ	22$
		MOV	ES,DX			;SEE IF NOW LEVEL_0
		SYM_CONV_ES
		CMP	ES:[BX]._SECT_LEVEL,0
		JNZ	22$
		OR	[SI]._SM_PLTYPE,MASK LEVEL_0_SECTION
		JMP	29$

24$:
		CMP	[SI]._SM_SECTION.SEGM,DX
		JZ	29$
		JMP	21$

28$:
		MOV	AX,FIX_TARGET_STUFF.FS_PTR.SEGM
		CMP	LDATA_SEGMOD.SEGM,AX
		JZ	3$
		JMP	20$

22$:
		;
		;NOW, IF THIS SEGMOD IS ALLOCATABLE, ADD
		;
		TEST	FIX_SEGMOD_STUFF._SM_PLTYPE,MASK SECTION_ASSIGNED
		JNZ	29$				;NOT ALLOCATABLE
		;
		;ADD THIS SEGMOD TO LIST OF ALLOCATABLE SEGMODS REFERENCING
		;THIS ALLOCATABLE SEGMOD...
		;
		MOV	DX,FIX_TARGET_STUFF.FS_PTR.SEGM
		MOV	CX,FIX_TARGET_STUFF.FS_PTR.OFFS
		MOV	AX,LDATA_SEGMOD.SEGM
		MOV	BX,LDATA_SEGMOD.OFFS
		CALL	INSTALL_LIBALLOC
29$:
		POPM	SI,DS
3$:
		ASSUME	DS:DGROUP
endif
		XOR	EAX,EAX
		MOV	EDI,FIX_LDATA_PTR

		MOV	ECX,FIX_OFFSET
if	fg_segm
		MOV	LATEST_PENT_GINDEX,EAX
endif

		ADD	EDI,ECX

		JMP	LOC_JMPTBL[ESI*4]

EXECUTE_FIXUPP	ENDP


LOC_0		PROC	NEAR
		;
		;SELF-RELATIVE SHORT JUMP
		;
		;IF FRAME = TARG OR GROUP(TARG)
		; AND TARGET = SEGMENT = LOC
		;
		RET

LOC_0		ENDP


LOC_1		PROC	NEAR
		;
		;SELF-RELATIVE NEAR JUMP
		;
		;CAN AT LEAST ADD IN OFFSET IF OFFSET IS NOT 32-BITS
		;
		MOV	EAX,FIX_TOFFSET
		XOR	ECX,ECX

		CMP	EAX,64K
		JC	L1$

		CMP	EAX,0FFFF0000H
		JA	L9$
L1$:
		ADD	WPTR [EDI],AX
		MOV	FIX_TOFFSET,ECX
		;
		;IF FRAME = TARG OR GROUP(TARG)
		; AND TARGET = SEGMENT = LOC
		;
		CALL	CHECK_SELF_REL
		JNZ	L9$
		;
		;YIPPEE! JUST SUBTRACT CURRENT LOCATION FROM ES:DI
		;
		TEST	EAX,0FFFF0000H
		JNZ	L9$

		ADD	EAX,2
		MOV	CL,-1

		SUB	WPTR [EDI],AX
		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,CL	;NO TARGET, IE, FIXUPP ELIMINATED
L9$:
		RET

LOC_1		ENDP


LOC_32SELF	PROC	NEAR
		;
		;SELF-RELATIVE 32-BIT JUMP...
		;
		;CAN AT LEAST ADD IN OFFSET
		;
		MOV	EAX,[EDI]
		MOV	ECX,FIX_TOFFSET

		XOR	EDX,EDX
		ADD	EAX,ECX

		MOV	FIX_TOFFSET,EDX
		MOV	[EDI],EAX

		;
		;IF FRAME = TARG OR GROUP(TARG)
		; AND TARGET = SEGMENT = LOC
		;
		CALL	CHECK_SELF_REL
		JNZ	L9$

		ADD	EAX,4
		MOV	ECX,[EDI]

		SUB	ECX,EAX
		MOV	AL,-1

		MOV	[EDI],ECX
		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,AL	;NO TARGET, IE, FIXUPP ELIMINATED
L9$:
		RET

LOC_32SELF	ENDP


CHECK_SELF_REL	PROC	NEAR
		;
		;
		;
		MOV	AL,BPTR FIX_FRAME_STUFF.FS_TYPE
		MOV	CL,BPTR FIX_TARGET_STUFF.FS_TYPE

		CMP	AL,FS_TYPE_TARG		;TARG*2
		JNZ	L9$			;NOPE, FAIL

		CMP	CL,FS_TYPE_SEGMENT	;SEGMENT*2
		JNZ	L9$

		MOV	ECX,FIX_TARGET_STUFF.FS_INDEX
		MOV	EAX,LDATA_SEGMOD_GINDEX

		CMP	EAX,ECX
		JNZ	L9$			;FAIL IF DIFFERENT SEGMOD
		;
		;YIPPEE! JUST SUBTRACT CURRENT LOCATION FROM ES:DI
		;
		;OK, SO, FIX_TOFFSET-CURLOC-4
		;
		MOV	EAX,LDATA_LOC
		MOV	ECX,FIX_OFFSET

		ADD	EAX,ECX
		CMP	EBX,EBX
L9$:
		RET

CHECK_SELF_REL	ENDP


LOC_8		PROC	NEAR
		;
		;LO-BYTE
		;
		CALL	CHECK_ASEG_OFFSET

		MOV	ECX,FIX_TOFFSET
		JNZ	L9$

		ADD	EAX,ECX
		MOV	CL,[EDI]

		CMP	EAX,255
		JBE	L8$

		CMP	EAX,-128
		JNC	L8$
L9$:
		RET

L8$:
		ADD	CL,AL
		MOV	AL,-1

		MOV	[EDI],CL
		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,AL

		RET

LOC_8		ENDP


LOC_12		PROC	NEAR
		;
		;HIGH BYTE
		;
		CALL	CHECK_ASEG_OFFSET

		MOV	ECX,FIX_TOFFSET
		JNZ	L9$

		MOV	DL,[EDI]
		ADD	EAX,ECX

		MOV	CL,-1
		ADD	DL,AH

		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,CL	;FIXUPP COMPLETED
		MOV	[EDI],DL

L9$:
		RET

LOC_12		ENDP


LOC_9		PROC	NEAR
		;
		;16-BIT OFFSET
		;
		;CAN AT LEAST GET RID OF OFFSET IF NOT 32-BIT
		;
		;IF TARG = ABSOLUTE, CAN COMPLETELY PROCESS PROBABLY...
		;
		MOV	EAX,FIX_TOFFSET
		XOR	ECX,ECX

		CMP	EAX,-64K
		JNC	L2$

		CMP	EAX,64K
		JNC	L9$
L2$:
		ADD	WPTR [EDI],AX
		MOV	FIX_TOFFSET,ECX

		CALL	CHECK_ASEG_OFFSET
		MOV	CL,-1
		JNZ	L9$

		ADD	WPTR [EDI],AX
		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,CL	;FIXUPP COMPLETED
L9$:
		RET

LOC_9		ENDP


LOC_13		PROC	NEAR
		;
		;16-BIT OFFSET, LOADER MODIFIED
		;
if	fg_segm
		;
		;NEED TO DETERMINE IF PENT IS NECESSARY
		;
LOC_130::
		GETT	AL,ENTRIES_POSSIBLE	;

		OR	AL,AL
		JZ	LOC_9			;

		CALL	LOC_9
LOC_131::					;FROM DWORD SPECIAL OFFSET
;		XOR	CL,CL			;ASSUME SEGMENT
LOC_132::					;FROM BASE
		;
		;
		;
		MOV	AL,FIX_SKIP_PENTS
		MOV	EBX,FIX_TARGET_STUFF.FS_TYPE

		OR	AL,AL
		JNZ	L9$			;SKIP ALL IF DEBUG INFORMATION, IOPL-CONF-CODE, ETC

		CMP	BL,-1
		JZ	L9$			;SKIP IF FULLY PROCESSED (ASEGS, CONSTANTS, NEAR CALLS)

		MOV	EDX,FIX_TARGET_STUFF.FS_INDEX	;SEGMOD, GROUP, SYMBOL, ASEG
		CALL	JMP_TABLE[EBX*4]
L9$:
ASEG_13:
RETT:
		RET

		;
		;UNDER WHAT CONDITIONS MAY I NOT BOTHER WITH PENT
		;
		;	FOR GROUPS, GROUP TYPE MUST BE ASEG, RARE, SO I WILL NOT BOTHER CHECKING, JUST INSTALL
		;		(WILL ALMOST ALWAYS BE DGROUP:0, BUT DO IT ANYWAY).
		;	FOR SEGMODS, AGAIN, TYPE MUST BE ASEG, OR FIXED, OR NOT IOPL IF PROTMODE
		;		;;;;;CANNOT KNOW IF ITS A COMDAT, OTHERWISE I CAN BE QUITE SURE. -COMDATS MUST BE REFERENCED AS SYMS
		;	FOR EXTERNALS, CAN IGNORE IF ASEG OR CONST OR IMPORT OR FLOAT_SYM.  IF RELOC, TEST SEGMOD AS ABOVE,
		;		 BUT STORE AS SYMBOL
		;	FOR ASEG, SIMPLY IGNORE
		;
		;ALL OTHERS MUST ASSUME POSSIBLE ENTRY POINT
		;
GROUP_13:
		MOV	CL,2
		JMP	STORE_INDEX

SEGMOD_13:
		;
		;IF ASEG, SKIP IT
		;DON'T BOTHER, NOT LIKELY IN SEGMENTED MODE...
		;
		;INSTALL SEGMOD-OFFSET INTO TABLE
		;
		MOV	CL,0				;0=SEGMENT
STORE_INDEX:
		;
		;SEGMOD, GROUP, SYMBOL INDEX IN DX
		;
		MOV	EBX,FIX_TOFFSET

		MOVSX	EAX,WPTR [EDI]

		AND	ECX,0FH
		ADD	EAX,EBX
		;
		;EDX IS GINDEX
		;EAX IS OFFSET FROM ABOVE
		;ECX IS TYPE
		;
		CALL	INSTALL_PENT
		MOV	DL,FIX_COMDAT_PENTS

		OR	DL,DL		;IN CERTAIN CASES, WE MUST KEEP TRACK OF THESE
		JNZ	SI_1

		RET

SI_1:
		;
		;THIS IS ONE OF TWO CASES:
		;
		;	1. UNREFERENCED COMDATS - WE WILL DECREMENT PENT COUNTS IF NEVER REFERENCED
		;	2. REFERENCED BUT NO KNOWN SEGMENT - WE WILL ADJUST IF PROTMODE AND IOPL
		;
		CALL	INSTALL_SOFT_PENT
		RET

EXTERNAL_13:
		CONVERT	EAX,EDX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		MOV	BL,[EAX]._S_REF_FLAGS

		AND	BL,MASK S_FLOAT_SYM
		JNZ	RETT

		MOV	AL,[EAX]._S_NSYM_TYPE
		MOV	CL,1

		CMP	AL,NSYM_ASEG
		JZ	RETT

		CMP	AL,NSYM_CONST
		JZ	RETT

		CMP	AL,NSYM_IMPORT
		JNZ	STORE_INDEX

		RET

		ASSUME	EAX:NOTHING

ife	data_in_codeseg

		.DATA

endif

		ALIGN	4

JMP_TABLE	DD	SEGMOD_13,GROUP_13,EXTERNAL_13,ASEG_13


ife	data_in_codeseg

		.CODE	PASS1_TEXT

endif


else

LOC_130:
		JMP	LOC_9

endif

LOC_13		ENDP


CHECK_ASEG_OFFSET	PROC	NEAR
		;
		;IF TARG = CONSTANT OR TARG = SEGMENT AT
		;
		MOV	AL,BPTR FIX_FRAME_STUFF.FS_TYPE
		MOV	CL,BPTR FIX_TARGET_STUFF.FS_TYPE

		CMP	AL,FS_TYPE_TARG			;MUST BE FRAME(TARG)
		JNZ	L9$

		CMP	CL,FS_TYPE_SYMBOL		;EXTRN
		JNZ	L9$

		MOV	AL,FIX_NSYM_TYPE
		MOV	ECX,FIX_TARGET_STUFF.FS_INDEX

		CMP	AL,NSYM_CONST
		JNZ	L9$

		CONVERT	ECX,ECX,SYMBOL_GARRAY
		ASSUME	ECX:PTR SYMBOL_STRUCT

if	fg_segm
		MOV	DL,[ECX]._S_REF_FLAGS
endif
		MOV	EAX,[ECX]._S_OFFSET

if	fg_segm
		AND	DL,MASK S_FLOAT_SYM
		JNZ	EXT1
else
		CMP	ECX,ECX
endif

L9$:
		RET

GROUP_1:
		OR	AL,-1
		RET

if	fg_segm
EXT1:
		GETT	DL,OUTPUT_SEGMENTED
		MOV	AL,BPTR [ECX]._S_FLOAT_TYPE

		OR	DL,DL
		JZ	GROUP_1			;BETTER NOT, MAY TURN SEGMENTED LATER...

		AND	EAX,7
		RET
endif

CHECK_ASEG_OFFSET	ENDP


LOC_11		PROC	NEAR
		;
		;16:16 POINTER
		;
		MOV	EAX,FIX_TARGET_STUFF.FS_TYPE

		PUSH	EAX
		CALL	LOC_130		;SPECIAL 16-BIT OFFSET - DOES ENTRY EVEN IF PROTMODE

		POP	EAX
		MOV	ECX,FIX_OFFSET

		ADD	EDI,2		;POSSIBILITY CHECK...
		ADD	ECX,2

		MOV	FIX_TARGET_STUFF.FS_TYPE,EAX
		MOV	FIX_OFFSET,ECX
		;
		;PLUS WHATEVER ELSE IS NEEDED FOR RANGE CHECKING
		;
		CALL	LOC_10_A	;NO PENT
		MOV	ECX,FIX_OFFSET
		MOV	AL,FIX_NSYM_TYPE

		SUB	ECX,2
		CMP	AL,NSYM_CONST

		MOV	FIX_OFFSET,ECX
		JNZ	L5$

		MOV	AL,BPTR FIX_TARGET_STUFF.FS_TYPE
		MOV	CL,-1

		CMP	AL,FS_TYPE_SYMBOL
		JNZ	L5$

		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,AL
L5$:
if	fg_norm_exe OR fg_segm
		;
		;WHAT IF REALMODE, FARCALLTRANSLATE, AND NO EXEPACK?
		;OR, ENTRIES_POSSIBLE AND FARCALLTRANSLATE
		;
		JMP	LOC_11_FIX
endif
LOC_11_DONE::
		RET

LOC_11		ENDP


if	fg_norm_exe OR fg_segm

LOC_11_R	PROC	NEAR
		;
		;MAYBE REAL MODE, FARCALLTRANSLATE SELECTED, NO EXEPACK
		;OR SEGMENTED, REALMODE, FARCALLTRANSLATE, PENT
		;
		MOV	CL,FIX_SKIP_PENTS
		MOV	AL,CLASS_TYPE

		OR	CL,CL
		JNZ	LOC_11_DONE

		TEST	AL,MASK SEG_CLASS_IS_CODE
		JZ	LOC_11_DONE

		MOV	AL,FIX_SEGMOD_STUFF._SM_FLAGS_2
		MOV	ECX,FIX_OFFSET

		TEST	AL,MASK SM2_DATA_IN_CODE
		JNZ	LOC_11_DONE
		;
		OR	ECX,ECX	;IF ZERO, WE CANNOT TELL IF ITS A
		JZ	LOC_11_MAYBE	;FAR CALL OR WHAT...
LOC_11_M_RET:
		;
		;FARCALL?
		;
		MOV	AL,BPTR [EDI-3]

		CMP	AL,0EAH
		JZ	LOC_11_YES

		CMP	AL,9AH
		JZ	LOC_11_YES
		JMP	LOC_11_DONE

LOC_11_MAYBE:
		;
		;WE ARE AT OFFSET ZERO IN THE RECORD, IS THE PREVIOUS RECORD
		;USABLE?
		;
		MOV	EDX,PREV_DATA_PTR		;PREVIOUS RECORD VALID?
		ASSUME	EDX:PTR LDATA_HEADER_TYPE
		MOV	ECX,[EDI + (LDATA_HEADER_TYPE._LD_OFFSET-SIZE LDATA_HEADER_TYPE)-2]

		TEST	EDX,EDX
		JZ	LOC_11_DONE

		SUB	ECX,[EDX]._LD_OFFSET		;DISTANCE TO CURRENT RECORD FROM BEGINNING OF PREVIOUS
		JC	LOC_11_DONE			;NOPE...PREVIOUS IS LOGICALLY AFTER CURRENT

		CMP	[EDX]._LD_LENGTH,CX		;PREVIOUS REACHES AT LEAST FAR ENOUGH?
		JC	LOC_11_DONE			;NOPE
		;
		;
		;

;		MOV	AX,ES:[DI]._LD_SECOND_BLK	;IN CASE RECORD SPLITS BLOCKS...
;		ADD	DI,CX
;		ADD	DI,SIZE LDATA_HEADER_TYPE+2	;ADDRESS WE WILL LOOK BACK 3 FROM FOR JMP OR CALL
;		CMP	DI,PAGE_SIZE+3			;WILL -3 STILL BE IN BLOCK?
;		JC	LOC_11_M_RET			;YES, JUMP
;		SUB	DI,PAGE_SIZE-2			;ADJUST BY BLOCK SIZE ALLOWING FOR WORD COUNT AT START OF EACH BLOCK

		JMP	LOC_11_M_RET

LOC_11_YES:
		MOV	AL,BPTR FIX_TARGET_STUFF.FS_TYPE
		LEA	ESI,FIX_TARGET_STUFF
		CMP	AL,-1				;OPTIMIZED AWAY?
		JZ	LOC_11_DONE
		MOV	EDI,FIX_FARCALL_PTR
		XOR	EAX,EAX
		ADD	EDI,4
		CALL	STORE_OPTI
if	fg_segm
		GETT	CL,ENTRIES_POSSIBLE
		MOV	EAX,LATEST_PENT_GINDEX
		OR	CL,CL
		JZ	L6$
		MOV	[EDI],EAX
		ADD	EDI,4
L6$:
endif
		MOV	FIX_FARCALL_PTR,EDI
		CMP	EDI,OFF FARCALL_FIXUPP+INBUF_LEN-13
		JAE	L7$
		RET

L7$:
		CALL	FLUSH_FARCALL
		RET

LOC_11_R	ENDP

endif


LOC_DWORD_OFFSET1	PROC	NEAR
		;
		;
		;
if	fg_segm

LOC_DWORD_OFFSET2::
		GETT	AL,ENTRIES_POSSIBLE	;IF PROTMODE, MUST BE IOPL

		TEST	AL,AL
		JZ	LOC_DWORD_OFFSET	;FOR REAL, MUST BE MOVEABLE

		CALL	LOC_DWORD_OFFSET
		JMP	LOC_131

else

LOC_DWORD_OFFSET2::

endif

LOC_DWORD_OFFSET1	ENDP


LOC_DWORD_OFFSET	PROC	NEAR
		;
		;
		;
		MOV	ECX,[EDI]
		MOV	EAX,FIX_TOFFSET

		XOR	EDX,EDX
		ADD	EAX,ECX

		MOV	FIX_TOFFSET,EDX
		MOV	[EDI],EAX

		CALL	CHECK_ASEG_OFFSET	;CAN WE DO MORE?

		MOV	ECX,[EDI]
		JNZ	L9$

		ADD	EAX,ECX
		MOV	CL,-1

		MOV	[EDI],EAX
		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,CL	;FIXUPP COMPLETED
L9$:
		RET

LOC_DWORD_OFFSET	ENDP


LOC_FWORD_PTR	PROC	NEAR
		;
		;
		;
		MOV	EAX,FIX_TARGET_STUFF.FS_TYPE

		PUSH	EAX
		CALL	LOC_DWORD_OFFSET2	;DOES PENT

		MOV	ECX,FIX_OFFSET
		POP	EAX

		ADD	ECX,4
		MOV	FIX_TARGET_STUFF.FS_TYPE,EAX

		MOV	FIX_OFFSET,ECX
		ADD	EDI,4

		CALL	LOC_10_A		;NO PENT

		SUB	FIX_OFFSET,4
		RET

LOC_FWORD_PTR	ENDP


LOC_10_B	PROC	NEAR
		;
		;BASE
		;
if	fg_segm
		GETT	AL,ENTRIES_POSSIBLE	;IF PROTMODE, MUST BE IOPL

		OR	AL,AL
		JZ	L1$			;FOR REAL, MUST BE MOVEABLE
		CALL	LOC_132
		JMP	L2$

endif

L1$:
		XOR	EAX,EAX			;BASE OFFSET IS SIGNIFICANT IF ENTRIES POSSIBLE
		MOV	FIX_TOFFSET,EAX
L2$:
LOC_10_A::
		;
		;IF FRAME & TARG IS ASEG, WE ARE HOME FREE, JUST STORE IT...
		;
		;IF RELOCATABLE OR UNDEFINED, NEED TO COUNT IT AS A FIXUP
		;IF LIDATA, NEEDS SPECIAL PROCESSING
		;
		;ITS NOT LIKELY THAT WE WILL DO FULL REDUCTION, SO DON'T BOTHER EVEN LOOKING IF WE DON'T NEED A RELOC COUNT...
		;
if	fg_norm_exe
if	fg_pe OR fg_segm
		GETT	AL,OUTPUT_PE
		GETT	CL,OUTPUT_SEGMENTED

		OR	AL,CL
		JNZ	L9$			;DON'T BOTHER COUNTING...
endif

		GETT	AL,OUTPUT_COM_SYS	;COM OR SYS
		GETT	CL,EXEPACK_SELECTED	;NOT IF EXEPACKED EITHER...

		OR	AL,CL
		JNZ	L9$
if	fg_slrpack
		GETT	AL,SLRPACK_FLAG		;ANY KIND OF PACKING MEANS DON'T COUNT EM

		OR	AL,AL
		JNZ	L9$
endif
		;
		;SKIP IT IF IT IS A DEBUG RECORD...
		;
		MOV	AL,FIX_SEGMOD_STUFF._SM_FLAGS
		MOV	EBX,FIX_TARGET_STUFF.FS_TYPE

		TEST	AL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	L9$
		;
		;OK, TRY TO ELIMINATE THIS
		;
		MOV	EAX,FIX_TARGET_STUFF.FS_INDEX
		JMP	LOC_10_TABLE[EBX*4]

L10_TSEG::
		;
		;TARGET IS A SEGMENT
		;IF ASEG, REPLACE, ELSE COUNT IT
		;
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		MOV	AL,[EAX].SEGMOD_STRUCT._SM_FLAGS

		TEST	AL,MASK SEG_ASEG
		JZ	L10_RELOC
		JMP	L10_SKIP_FRAME


L10_TGRP::
		;
		;TARGET IS GROUP,
		;
		CONVERT	EAX,EAX,GROUP_GARRAY
		MOV	AL,[EAX].GROUP_STRUCT._G_TYPE

		TEST	AL,MASK SEG_ASEG
		JZ	L10_RELOC		;CAN'T RESOLVE, BUT ASEG...
		JMP	L10_SKIP_FRAME

L10_TEXT::
		;
		;TARGET IS A SYMBOL
		;IF ABSOLUTE, TRY REPLACING IT
		;
		CONVERT	EAX,EAX,SYMBOL_GARRAY
		MOV	BL,[EAX].SYMBOL_STRUCT._S_NSYM_TYPE

		CMP	BL,NSYM_CONST
		JZ	L10_SKIP_FRAME

		CMP	BL,NSYM_ASEG
		JZ	L10_SKIP_FRAME
L10_RELOC:
		;
		;ALL OF THIS JUST TO ESTIMATE SIZE OF EXEHDR
		;
		;ASSUMING IT IS RELOCATABLE...
		;
		MOV	ECX,FIXUPP_COUNT
		MOV	AL,LDATA_TYPE

		INC	ECX
		TEST	AL,MASK BIT_LI		;LI OR LE

		MOV	FIXUPP_COUNT,ECX
		JZ	L9$

		CALL	LIBASE_PRELIM
L9$:
		RET


L10_DOFRAME::
		CMP	FIX_FRAME_STUFF.FS_TYPE,FS_TYPE_TARG
		JNZ	L10_SKIP_FRAME

		ADD	WPTR [EDI],AX
		MOV	BPTR FIX_TARGET_STUFF.FS_TYPE,-1
L10_SKIP_FRAME:
		RET

else

		RET
endif

LOC_10_B	ENDP


BAD_LOC		PROC	NEAR

		MOV	AL,UNREC_FIXUPP_ERR
		CALL	FIXUPP_ERROR
		RET

BAD_LOC		ENDP


T_GROUP		PROC	NEAR

F_GROUP::
		NEXT_INDEX	TG_L

		CONVERT_LINDEX_EAX_EAX		GROUP_LARRAY,EDX

		MOV	[EDI],EAX

		RET

		DOLONG	TG_L

T_GROUP		ENDP


T_EXTERNAL	PROC	NEAR
F_EXTERNAL::
		NEXT_INDEX	TE_L
		MOV	ECX,EXTDEF_DELTA

		ADD	EAX,ECX
		CONVERT_LINDEX_EAX_EAX	SYMBOL_LARRAY,EDX
T_EXTERNAL_VIRDEF::
		MOV	[EDI],EAX
		CONVERT	EDX,EAX,SYMBOL_GARRAY
		ASSUME	EDX:PTR SYMBOL_STRUCT

		MOV	ECX,EAX				;SAVE GINDEX
		MOV	AL,REFERENCE_FLAGS		;PROBABLY EITHER S_HARD_REF OR S_SOFT_REF

		MOV	BL,[EDX]._S_REF_FLAGS
		MOV	AH,FS_TYPE_TARG

		OR	AL,BL
		MOV	BL,[EDX]._S_NSYM_TYPE

		MOV	[EDX]._S_REF_FLAGS,AL
		TEST	AL,MASK S_FLOAT_SYM

		MOV	FIX_NSYM_TYPE,BL
		JNZ	ERF_2

		CMP	BL,NSYM_CONST
		JZ	ERF_2
ERF_3:
		TEST	AL,MASK S_REFERENCED+MASK S_HARD_REF
		JZ	ERF_1

		RET

		DOLONG	TE_L

ERF_2:
		;
		;CONSTANTS AND FLOAT SYMBOLS IGNORE FRAME STUFF, MAKE IT FRAME(TARG)
		;
		MOV	BPTR FIX_FRAME_STUFF.FS_TYPE,AH		;TARG*2
		JMP	ERF_3

ERF_1:
		;
		;THIS SYMBOL HAS ONLY BEEN SOFT REFERENCED, MAKE SURE IT IS IN LIST FOR THIS COMDAT...
		;
		MOV	EAX,ECX
		JMP	INSTALL_SOFT_REF

T_EXTERNAL	ENDP


T_ABSOLUTE	PROC	NEAR
F_ABSOLUTE::
		MOV	AL,BPTR [ESI]

		MOV	AH,BPTR [ESI+1]
		ADD	ESI,2

		AND	EAX,0FFFFH

		MOV	[EDI],EAX		;ABSOLUTE PARAGRAPH

		RET

T_ABSOLUTE	ENDP


T_SEGMENT	PROC	NEAR

		NEXT_INDEX	TS_L

		;The infamous Bugzilla 424
		;CMP	EAX,16K
		;JA	T_SEG_MVIRDEF
L1$:
		CONVERT_LINDEX_EAX_EAX	SEGMOD_LARRAY,EDX
L2$:
		MOV	[EDI],EAX
T_OTHERS::
		RET

		DOLONG	TS_L

T_SEG_MVIRDEF:
		;
		;INDEX >16K, MAYBE A BORLAND VIRDEF??
		;
		CONVERT_MYCOMDAT_EAX_ECX
		ASSUME	ECX:PTR MYCOMDAT_STRUCT

		MOV	DL,[EDI-4]
		JC	L1$

		ADD	DL,FS_TYPE_SYMBOL-FS_TYPE_SEGMOD
		MOV	EAX,[ECX]._MCD_SYMBOL_GINDEX
		;
		;CHANGE INDEX TYPE FROM SEGMOD TO EXTERNAL...
		;
		MOV	[EDI-4],DL
		JMP	T_EXTERNAL_VIRDEF

T_SEGMENT	ENDP


F_LOC		PROC	NEAR
		;
		;WE WANT (TARG) IF POSSIBLE
		;
		MOV	ECX,FIX_LDATA_SEGMENT_GINDEX	;FOR COMDAT...
		MOV	EAX,LDATA_SEGMOD_GINDEX

		TEST	ECX,ECX
		JZ	F_OTHERS

		TEST	EAX,EAX
		JZ	BAD_THREAD1

		MOV	BPTR [EDI-4],FS_TYPE_SEGMOD		;MARK IT SEGMENT TYPE

		JMP	F_SEG_1

BAD_THREAD1:
		MOV	AL,BAD_LOC_ERR
		push	EAX
		call	_err_abort

F_LOC		ENDP


F_SEGMENT	PROC	NEAR
		;
		;
		;
		NEXT_INDEX	FS_L

		;The infamous Bugzilla 424
		;CMP	EAX,16K
		;JA	F_SEG_MVIRDEF
L1$:
		CONVERT_LINDEX_EAX_EAX		SEGMOD_LARRAY,EDX
F_SEG_1::
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	EAX,[EAX]._SM_BASE_SEG_GINDEX

		MOV	[EDI],EAX
F_OTHERS::
F_TARG::
		RET

		ASSUME	EAX:NOTHING


		DOLONG	FS_L

F_SEG_MVIRDEF:
		;
		;INDEX >16K, MAYBE A BORLAND VIRDEF??
		;
		CONVERT_MYCOMDAT_EAX_ECX
		JC	L1$
		MOV	EAX,[ECX]._MCD_SYMBOL_GINDEX
		;
		;CHANGE INDEX TYPE FROM SEGMOD TO EXTERNAL...
		;
		ADD	BPTR [EDI-4],FS_TYPE_SYMBOL-FS_TYPE_SEGMOD
		JMP	T_EXTERNAL_VIRDEF

F_SEGMENT	ENDP


F_BAD::
		MOV	AL,UNRECOGNIZED_FIXUPP_FRAME_ERR
		push	EAX
		call	_err_abort


T_ABSOLUTE_OFFSET	PROC	NEAR
		CALL	T_ABSOLUTE
		JMP	DO_OFFSET

T_GROUP_OFFSET::
		CALL	T_GROUP
		JMP	DO_OFFSET

T_EXTERNAL_OFFSET::
		CALL	T_EXTERNAL
		JMP	DO_OFFSET

T_SEGMENT_OFFSET::
		CALL	T_SEGMENT
DO_OFFSET::
		MOV	DL,FIX_SIZE
		MOV	EAX,DPTR [ESI]

		AND	DL,MASK BIT_32
		JZ	DO_OFFSET_16

		ADD	ESI,4
		MOV	FIX_TOFFSET,EAX

		RET

DO_OFFSET_16:
		MOVSX	EAX,AX			;NEED SIGN EXTENDED

		ADD	ESI,2
		MOV	FIX_TOFFSET,EAX

		RET

T_ABSOLUTE_OFFSET	ENDP


F_T_0		PROC	NEAR
		;
		;
		;
		AND	EBX,3

		LEA	EDX,PRE_THREADS[EBX*8]+4*SIZE THREAD_STUFF_STRUCT
		ASSUME	EDX:PTR THREAD_STUFF_STRUCT,EBX:NOTHING,EDI:NOTHING

		MOV	EAX,[EDX+EBX*8].FS_TYPE
		MOV	ECX,[EDX+EBX*8].FS_INDEX

		MOV	[EDI-4],EAX
		MOV	[EDI],ECX

		MOV	EAX,[EDX+EBX*8].FS_FILLER
		ADD	EDI,4

		TEST	EAX,EAX
		JZ	BAD_THREAD

		RET

BAD_THREAD:
		MOV	AL,BAD_THREAD_ERR
		push	EAX
		call	_err_abort

T_T_0::
		AND	EBX,3

		LEA	EDX,PRE_THREADS[EBX*8]
		ASSUME	EDX:PTR THREAD_STUFF_STRUCT,EBX:NOTHING,EDI:NOTHING

		MOV	EAX,[EDX+EBX*8].FS_TYPE
		MOV	ECX,[EDX+EBX*8].FS_INDEX

		MOV	[EDI-4],EAX
		MOV	[EDI],ECX

		MOV	EAX,[EDX+EBX*8].FS_FILLER
		ADD	EDI,4

		TEST	EAX,EAX
		JZ	BAD_THREAD

		RET

T_T_0_OFFSET::
		CALL	T_T_0
		JMP	DO_OFFSET

F_T_0		ENDP


		PUBLIC	PRELIM

PRELIM		PROC	NEAR
		;
		;HERE COMES PRELIM
		;
		MOV	BL,BYTE PTR[ESI]
		INC	ESI

		PUSH	EBX

		SHR	BL,4
		LEA	EDI,FIX_FRAME_STUFF.FS_INDEX

		AND	EBX,0FH
		MOV	BUFFER_OFFSET,ESI

		MOV	FIX_FRAME_STUFF.FS_TYPE,EBX

		CALL	PRELIM_FRAME_TABLE[EBX*4]		;GET PROPER FRAME

		POP	EBX
		LEA	EDI,FIX_TARGET_STUFF.FS_INDEX

		MOV	EAX,EBX
		AND	EBX,0FH

		AND	EAX,3
		XOR	ECX,ECX

		MOV	FIX_TARGET_STUFF.FS_TYPE,EAX
		MOV	FIX_TOFFSET,ECX			;ASSUME OFFSET = 0 ?

		JMP	PRELIM_TARGET_TABLE[EBX*4]

PRELIM		ENDP


if	fg_norm_exe


LIBASE_PRELIM	PROC	NEAR
		;
		;JUST HANDLES 16-BIT RECORDS...
		;
		MOV	AL,LDATA_TYPE
		PUSH	EBX

		TEST	AL,MASK BIT_32
		JNZ	L01$

		MOV	ESI,FIX_LDATA_PTR
		MOV	FIX_ESP_SAVE,ESP		;FOR QUICK RECOVERY
L0$:
		CALL	L1$

		CMP	FIX_END_OF_RECORD,ESI
		JA	L0$
L01$:
		MOV	AL,LIDATA_ERR
		push	EAX
		call	_err_abort
		RET				;ACTUALLY FAILURE...

L1$:
		MOV	EDX,1			;INITIAL REPEAT COUNT
		MOV	ECX,1			;BLOCK COUNT
L2$:
		PUSHM	EDX,ECX

		MOVZX	EAX,WPTR [ESI]
		MUL	EDX
		MOVZX	ECX,WPTR [ESI+2]

		MOV	EDX,EAX
		ADD	ESI,4

		TEST	ECX,ECX
		JZ	L5$

		CALL	L2$
L4$:
		POPM	ECX,EDX

		DEC	ECX
		JNZ	L2$

		RET

L5$:
		MOV	CL,BYTE PTR[ESI]
		ADD	ESI,ECX

		INC	ESI

		CMP	EDI,ESI
		JNC	L4$

		DEC	EDX
		MOV	ESP,FIX_ESP_SAVE

		ADD	FIXUPP_COUNT,EDX
		POP	EBX

		RET

LIBASE_PRELIM	ENDP

endif


FIXUPP_MODEND	PROC
		;
		;
		;
		PUSH	EBP
		MOV	EBP,ESP
		SUB	ESP,SIZE FIX_VARS

		MOV	EAX,CURNMOD_GINDEX
		MOV	FIX_SIZE,CL
		MOV	MODEND_OWNER_GINDEX,EAX

		MOV	FIX_NEW_PTR,OFF NEW_FIXUPP
		MOV	LDATA_SEGMOD_GINDEX,0		;INVALIDATE 'LOC' FRAME TYPE
		CALL	PRELIM

		LEA	ESI,FIX_TARGET_STUFF
		CALL	STORE_OPTIMAL_MODEND

		OR	FIX_SIZE,MASK BIT_ME
		MOV	EAX,FIX_NEW_PTR
		LEA	ESI,NEW_FIXUPP
		SUB	EAX,ESI
		JZ	L9$
		MOV	ECX,EAX
		ADD	EAX,4
		TILLP2_POOL_ALLOC
		MOV	EDI,EAX
		MOV	MODEND_ADDRESS,EAX

		LEA	EAX,[ECX]

		STOSD

		REP	MOVSB
L9$:
		MOV	ESP,EBP
		POP	EBP
		RET

FIXUPP_MODEND	ENDP


		.CONST

		ALIGN	4

FRAME_OPTI_TABLE	LABEL	DWORD
		DD	FRAME_SEGMENT
		DD	FRAME_OPTIMUM		;GROUP, NOTHING TO DO NOW...
		DD	FRAME_EXTERNAL
		DD	FRAME_ABSOLUTE
		DD	YES_LOC
		DD	FRAME_OPTIMUM		;TARG
		DD	FRAME_OPTIMUM		;BAD
		DD	FRAME_OPTIMUM		;BAD


DT_TABLE	LABEL	DWORD			;DO THREADS
		DD	T_SEGMENT
		DD	T_GROUP
		DD	T_EXTERNAL
		DD	T_ABSOLUTE
		DD	T_SEGMENT
		DD	T_GROUP
		DD	T_EXTERNAL
		DD	T_ABSOLUTE
		DD	F_SEGMENT
		DD	F_GROUP
		DD	F_EXTERNAL
		DD	F_ABSOLUTE
		DD	F_OTHERS		;F_LOC (PROCESS LATER)
		DD	F_OTHERS		;F_TARG (PROCESS LATER)
		DD	F_BAD
		DD	F_BAD


		ALIGN	4

PRELIM_FRAME_TABLE LABEL DWORD

		DD	F_SEGMENT
		DD	F_GROUP
		DD	F_EXTERNAL
		DD	F_ABSOLUTE
		DD	F_LOC
		DD	F_TARG
		DD	F_BAD
		DD	F_BAD
		DD	F_T_0
		DD	F_T_0
		DD	F_T_0
		DD	F_T_0
		DD	F_T_0
		DD	F_T_0
		DD	F_T_0
		DD	F_T_0


PRELIM_TARGET_TABLE LABEL DWORD

		DD	T_SEGMENT_OFFSET
		DD	T_GROUP_OFFSET
		DD	T_EXTERNAL_OFFSET
		DD	T_ABSOLUTE_OFFSET
		DD	T_SEGMENT
		DD	T_GROUP
		DD	T_EXTERNAL
		DD	T_ABSOLUTE
		DD	T_T_0_OFFSET
		DD	T_T_0_OFFSET
		DD	T_T_0_OFFSET
		DD	T_T_0_OFFSET
		DD	T_T_0
		DD	T_T_0
		DD	T_T_0
		DD	T_T_0


FRAME_SEGMENT_TABLE	LABEL	DWORD

		DD	F_SEG_T_SEG		;FRAME = SEG, TARG = SEG
		DD	TRY_LOC			;FRAME = SEG, TARG = GROUP
		DD	F_SEG_T_EXT		;FRAME = SEG, TARG = EXTERNAL
		DD	TRY_LOC			;FRAME = SEG, TARG = ABSOLUTE


		ALIGN	4

LOC_JMPTBL	LABEL	DWORD
		;16-BIT SELF-RELATIVE
		DD	LOC_0
		DD	LOC_1
		REPT	3
		DD	BAD_LOC
		ENDM
		DD	BAD_LOC			;WAS PHARLAP_LOC_32
		DD	2 DUP(BAD_LOC)

		;32-BIT SELF-RELATIVE
		DD	BAD_LOC
		DD	LOC_32SELF
		REPT	6
		DD	BAD_LOC
		ENDM
		;16-BIT SEGMENT-RELATIVE
		DD	LOC_8
		DD	LOC_9
		DD	LOC_10_B
		DD	LOC_11
		DD	LOC_12
		DD	LOC_13		;WINDOWS-OS/2 SPECIAL
		DD	BAD_LOC		;WAS PHAR_FWORD_PTR
		DD	BAD_LOC
		;32-BIT SEGMENT-RELATIVE
		DD	BAD_LOC
		DD	LOC_DWORD_OFFSET
		DD	LOC_DWORD_OFFSET	;TLS
		DD	LOC_FWORD_PTR
		DD	BAD_LOC
		DD	LOC_DWORD_OFFSET1
		DD	BAD_LOC
		DD	BAD_LOC

LOC_10_TABLE	LABEL	DWORD
		;
		DD	L10_TSEG
		DD	L10_TGRP
		DD	L10_TEXT
		DD	L10_DOFRAME		;ASEG, NOT SUPPORTED BY MS

		;??

		.CONST

LOC_SIZE	LABEL	BYTE
		;16-BIT SELF-RELATIVE
		DB	1	;BYTE
		DB	2	;WORD
		DB	3 DUP(1)
		DB	4	;PHARLAP 32 SELF
		DB	2 DUP(1)
		;32-BIT EQUIVALENTS OF ABOVE...
		DB	1
		DB	4
		DB	4	;TLS
		DB	5 DUP(1)
		;16-BIT SEGMENT RELATIVE
BITS_TABLE	DB	1	;BYTE
		DB	2	;WORD
		DB	2	;WORD - BASE
		DB	4	;PTR
		DB	1	;HIGH BYTE ;12
		DB	2	;WIERD WORD
		DB	6	;PHARLAP FWORD
		DB	1
		;32-BIT SEGMENT RELATIVE
		DB	1	;BYTE ?
		DB	4	;DWORD
		DB	4	;TLS
		DB	6	;FWORD
		DB	1
		DB	4	;WEIRD DWORD
		DB	2 DUP(1)

if	fg_phar

PHAR_TO_MS	DB	0,1,2,3,4,9,6,7
		DB	8,9,10,11,12,13,14,15
		DB	16,17,18,19,20,25,27,23
		DB	24,25,26,27,28,29,30,31

endif

		END

